﻿#include "hardwarewidget.h"
#include "qdebug.h"
#include "ui_hardwarewidget.h"
#include "attributepaneladapter.h"
#include <QStackedWidget>
#include <QTabBar>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QInputDialog>
#include <QSignalBlocker>

#include "hardwareeditorpresenter.h"

/**
 * @brief HardwareWidget::HardwareWidget
 * @details 构造硬件模板编辑界面，初始化属性面板与信号绑定。
 * @param type 模板类型。
 * @param parent Qt 父对象。
 */
HardwareWidget::HardwareWidget(const HardwareTemplateType type, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::HardwareWidget)
    , m_type(type)
    , m_SignalGeneratorWidget(new QGroupBox)
    , m_AmplifierWidget(new QGroupBox)
    , m_PowerMeterWidget(new QGroupBox)
    , m_AntennaWidget(new QGroupBox)
    , m_ConnectorWidget(new QGroupBox)
    , m_FieldProbeWidget(new QGroupBox)
    , m_ReceiverWidget(new QGroupBox)
    , m_CurrentProbeWidget(new QGroupBox)
{
    ui->setupUi(this);

    attrAdapter_ = new AttributePanelAdapter(
        ui->comboBox_Model,
        ui->comboBox_InterfaceType,
        ui->lineEdit_Addr,
        this);
    attrAdapter_->setEnabled(false); // 初始未选中任何节点
    initAttributeWidgets();

    m_attributeStackedWidget = new QStackedWidget(ui->scrollAreaHT->widget());
    specificAdapter_ = new SpecificAttrPanelAdapter(
        ui->scrollAreaHT->widget(), m_attributeStackedWidget,
        // SG
        m_SignalGeneratorWidget, m_SG_LevelMinEdit, m_SG_LevelMaxEdit,
        // Amp
        m_AmplifierWidget, m_PA_InputLevelMaxEdit,
        m_PA_CouplingConstantRadio, m_PA_CouplingConstEdit,
        m_PA_CouplingTableRadio, m_PA_FWDCouplingTableBox, m_PA_REVCouplingTableBox,
        // PM
        m_PowerMeterWidget, m_PM_ChannelBox,
        // ANT
        m_AntennaWidget, m_Ant_HFactorsBox, m_Ant_VFactorsBox,
        // CONN
        m_ConnectorWidget, m_Con_ConstantRadio, m_Con_constValueEdit,
        m_Con_TableRadio, m_Con_tableBox, m_SwitchWidget, m_SwitchSelection, m_SwitchChannel,
        // FP
        m_FieldProbeWidget, m_FP_CorrectionTableBox,
        // CP
        m_CurrentProbeWidget, m_CP_TransferCharacteristicTableBox,
        // RX
        m_ReceiverWidget,
        this);

    ui->scrollAreaHT->setFrameShape(QFrame::NoFrame);
    ui->scrollAreaHT->setWidgetResizable(true);
    ui->scrollAreaHT->viewport()->setAutoFillBackground(false);
    ui->scrollAreaHT->widget()->setAutoFillBackground(false);
    m_attributeStackedWidget->setAutoFillBackground(false);
    ui->scrollAreaHT->viewport()->setObjectName("myViewport");
    ui->scrollAreaHT->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->scrollAreaHT->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    // 重命名输入框
    m_tabNameEdit = new QLineEdit(this);
    m_tabNameEdit->setObjectName("m_tabNameEdit");
    m_tabNameEdit->hide();
    m_tabNameEdit->setToolTip(tr("Input tab name"));
    m_tabNameEdit->installEventFilter(this);
    ui->tabWidget_ht->installEventFilter(this);
    ui->tabWidget_ht->tabBar()->setDrawBase(false);
    connect(ui->tabWidget_ht, &QTabWidget::tabBarDoubleClicked, this, &HardwareWidget::on_tabBarClicked);
    connect(m_tabNameEdit, &QLineEdit::editingFinished, this, &HardwareWidget::on_setTabName);
    connect(m_tabNameEdit, &QLineEdit::returnPressed, this, &HardwareWidget::on_setTabName);

    connect(ui->comboBox_htName, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &HardwareWidget::on_comboBox_htName_currentIndexChanged);
    connect(ui->tabWidget_ht, &QTabWidget::currentChanged,
            this, &HardwareWidget::on_tabWidget_ht_currentChanged);

    loadAndDisplayAllTemplates();
}

/**
 * @brief HardwareWidget::~HardwareWidget
 * @details 析构时释放自动生成的 UI。
 */
HardwareWidget::~HardwareWidget()
{
    delete ui;
}

/**
 * @brief HardwareWidget::eventFilter
 * @details 处理标签重命名编辑框的点击外部关闭逻辑。
 * @param obj 事件目标对象。
 * @param event 事件指针。
 * @return 若事件被消费返回 true。
 */
bool HardwareWidget::eventFilter(QObject *obj, QEvent *event)
{
    if (m_tabNameEdit->isVisible() && event->type() == QEvent::MouseButtonRelease) {
        auto *me = static_cast<QMouseEvent *>(event);
        QPoint posInEdit = m_tabNameEdit->mapFromGlobal(me->globalPos());
        if (!m_tabNameEdit->rect().contains(posInEdit)) {
            Q_EMIT m_tabNameEdit->editingFinished();
            return true;
        }
    }
    return QWidget::eventFilter(obj, event);
}

/**
 * @brief HardwareWidget::loadAndDisplayAllTemplates
 * @details 载入所有硬件模板并为每个模板创建连接图页面。
 */
void HardwareWidget::loadAndDisplayAllTemplates()
{
    ui->tabWidget_ht->clear();
    presenters_.clear();

    const auto &overviews = DataManager::instance()->getHardwareTemplateOverviews();
    for (const auto &ov : overviews) {
        HardwareTemplatePtr doc = DataManager::instance()->getFullHardwareTemplate(ov.id);
        if (!doc || doc->type != m_type)
            continue;

        auto *conn = new ConnectingWindow(m_type, this);
        conn->setData(doc);

        auto *presenter = new HardwareEditorPresenter(doc, conn, this);
        presenter->setSelectedRole(DeviceRole::SignalGenerator);
        presenter->bind();
        presenters_.push_back(presenter);

        // 只放连接图
        auto *page = new QWidget(this);
        auto *h = new QHBoxLayout(page);
        h->setContentsMargins(0, 0, 0, 0);
        h->addWidget(conn);

        ui->tabWidget_ht->addTab(page, doc->name);
    }

    updateComboBoxName();

    if (ui->tabWidget_ht->count() > 0) {
        activePresenterIndex_ = 0;
        presenters_[0]->setAttrView(attrAdapter_);
        presenters_[0]->setSpecificView(specificAdapter_);
    }
}

/**
 * @brief HardwareWidget::updateComboBoxName
 * @details 将当前标签文本同步到模板名称下拉框。
 */
void HardwareWidget::updateComboBoxName()
{
    QSignalBlocker blk(ui->comboBox_htName);
    ui->comboBox_htName->clear();
    QStringList tabNames;
    for (int i = 0; i < ui->tabWidget_ht->count(); ++i)
        tabNames.append(ui->tabWidget_ht->tabText(i));
    ui->comboBox_htName->addItems(tabNames);
    ui->comboBox_htName->setCurrentIndex(ui->tabWidget_ht->currentIndex());
}

/**
 * @brief HardwareWidget::initAttributeWidgets
 * @details 初始化右侧属性区域的控件与布局。
 */
void HardwareWidget::initAttributeWidgets()
{
    m_SignalGeneratorWidget->setTitle(tr("SignalGeneratorAttribute"));
    m_SignalGeneratorWidget->setMaximumWidth(267);
    QLabel *labLevel = new QLabel(tr("Level Range"));
    m_SG_LevelMinEdit = new QLineEdit;
    m_SG_LevelMaxEdit = new QLineEdit;
    m_SG_LevelMinEdit->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
    m_SG_LevelMaxEdit->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));

    QHBoxLayout *hLayout = new QHBoxLayout;
    hLayout->setMargin(0);
    hLayout->setSpacing(6);
    hLayout->addWidget(m_SG_LevelMinEdit);
    hLayout->addWidget(new QLabel("-"));
    hLayout->addWidget(m_SG_LevelMaxEdit);
    hLayout->addWidget(new QLabel("dBm"));

    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->setContentsMargins(5, 9, 5, 9);
    vlayout->setSpacing(6);
    vlayout->addWidget(labLevel);
    vlayout->addLayout(hLayout);
    vlayout->addStretch();
    m_SignalGeneratorWidget->setLayout(vlayout);

    m_AmplifierWidget->setTitle(tr("AmplifierAttribute"));
    m_AmplifierWidget->setMaximumWidth(267);
    m_PA_InputLevelMaxEdit = new QLineEdit;
    m_PA_InputLevelMaxEdit->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
    QHBoxLayout *hLayout2 = new QHBoxLayout;
    hLayout2->setMargin(0);
    hLayout2->setSpacing(6);
    hLayout2->addWidget(m_PA_InputLevelMaxEdit);
    hLayout2->addWidget(new QLabel("dBm"));

    m_PA_CouplingConstantRadio = new QRadioButton(tr("Coupling Constant"));
    m_PA_CouplingConstantRadio->setChecked(true);
    m_PA_CouplingConstEdit = new QLineEdit;
    m_PA_CouplingConstEdit->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
    QHBoxLayout *hLayout3 = new QHBoxLayout;
    hLayout3->setMargin(0);
    hLayout3->setSpacing(1);
    hLayout3->addWidget(m_PA_CouplingConstantRadio);
    hLayout3->addWidget(m_PA_CouplingConstEdit);
    hLayout3->addWidget(new QLabel("dBm"));
    hLayout3->addStretch(1);

    m_PA_CouplingTableRadio = new QRadioButton(tr("Coupling Table"));
    m_PA_FWDCouplingTableBox = new QComboBox;
    m_PA_REVCouplingTableBox = new QComboBox;
    m_PA_FWDCouplingTableBox->setToolTip(tr("AttTables"));
    m_PA_REVCouplingTableBox->setToolTip(tr("AttTables"));

    QHBoxLayout *hLayout4 = new QHBoxLayout;
    hLayout4->setMargin(0);
    hLayout4->addSpacing(30);
    hLayout4->addWidget(new QLabel(tr("FWD")), 0);
    hLayout4->addWidget(m_PA_FWDCouplingTableBox, 1);

    QHBoxLayout *hLayout5 = new QHBoxLayout;
    hLayout5->setMargin(0);
    hLayout5->addSpacing(30);
    hLayout5->addWidget(new QLabel(tr("REV")), 0);
    hLayout5->addWidget(m_PA_REVCouplingTableBox, 1);

    QVBoxLayout *vlayout2 = new QVBoxLayout;
    vlayout2->setContentsMargins(5, 9, 5, 9);
    vlayout2->addWidget(new QLabel(tr("Max Input Level")));
    vlayout2->addLayout(hLayout2);
    vlayout2->addLayout(hLayout3);
    vlayout2->addSpacing(5);
    vlayout2->addWidget(m_PA_CouplingTableRadio);
    vlayout2->addLayout(hLayout4);
    vlayout2->addLayout(hLayout5);
    m_AmplifierWidget->setLayout(vlayout2);

    m_PowerMeterWidget->setTitle(tr("PowerMeterAttribute"));
    m_PowerMeterWidget->setMaximumWidth(267);
    m_PM_ChannelBox = new QComboBox;
    m_PM_ChannelBox->addItem("");
    m_PM_ChannelBox->addItem("A");
    m_PM_ChannelBox->addItem("B");
    QHBoxLayout *hLayout6 = new QHBoxLayout;
    hLayout6->setMargin(0);
    hLayout6->addWidget(new QLabel(tr("Channel")));
    hLayout6->addWidget(m_PM_ChannelBox);
    hLayout6->addStretch();
    QVBoxLayout *vlayout3 = new QVBoxLayout;
    vlayout3->setContentsMargins(5, 15, 5, 9);
    vlayout3->addLayout(hLayout6);
    vlayout3->addStretch();
    m_PowerMeterWidget->setLayout(vlayout3);

    m_AntennaWidget->setTitle(tr("AntennaAttribute"));
    m_AntennaWidget->setMaximumWidth(267);
    m_Ant_HFactorsBox = new QComboBox;
    m_Ant_VFactorsBox = new QComboBox;
    m_Ant_HFactorsBox->setToolTip(tr("TransducerTables"));
    m_Ant_VFactorsBox->setToolTip(tr("TransducerTables"));
    QHBoxLayout *hLayout7 = new QHBoxLayout;
    hLayout7->setMargin(0);
    hLayout7->addWidget(new QLabel(tr("Horizontal")));
    hLayout7->addWidget(m_Ant_HFactorsBox);
    hLayout7->addStretch();
    QHBoxLayout *hLayout8 = new QHBoxLayout;
    hLayout8->setMargin(0);
    hLayout8->addWidget(new QLabel(tr("Vertical")));
    hLayout8->addWidget(m_Ant_VFactorsBox);
    hLayout8->addStretch();
    QVBoxLayout *vlayout4 = new QVBoxLayout;
    vlayout4->setContentsMargins(5, 15, 5, 9);
    vlayout4->addLayout(hLayout7);
    vlayout4->addLayout(hLayout8);
    vlayout4->addStretch();
    m_AntennaWidget->setLayout(vlayout4);

    m_ConnectorWidget->setTitle(tr("ConnectorAttribute"));
    m_ConnectorWidget->setMaximumWidth(267);
    m_Con_constValueEdit = new QLineEdit;
    m_Con_tableBox = new QComboBox;
    m_Con_tableBox->setToolTip(tr("AttTables"));
    m_Con_ConstantRadio = new QRadioButton(tr("ATT Constant"));
    m_Con_TableRadio = new QRadioButton(tr("ATT Table"));
    m_SwitchWidget = new QWidget(m_ConnectorWidget);
    m_SwitchWidget->setContentsMargins(0, 7, 0, 0);
    QGridLayout *swLayout = new QGridLayout;
    swLayout->setMargin(0);
    m_SwitchSelection = new QComboBox;
    m_SwitchSelection->addItem("1");
    m_SwitchSelection->addItem("2");
    m_SwitchSelection->addItem("3");
    m_SwitchChannel = new QComboBox;
    m_SwitchChannel->addItem("0");
    m_SwitchChannel->addItem("1");
    m_SwitchChannel->addItem("2");
    m_SwitchChannel->addItem("3");
    m_SwitchChannel->addItem("4");
    m_SwitchChannel->addItem("5");
    m_SwitchChannel->addItem("6");
    m_SwitchSelection->setMinimumWidth(50);
    m_SwitchChannel->setMinimumWidth(50);

    swLayout->addWidget(new QLabel(tr("SwitchSelection")), 0, 0, 1, 1, Qt::AlignCenter);
    swLayout->addWidget(new QLabel(tr("ChannelSelection")), 0, 1, 1, 1, Qt::AlignCenter);
    swLayout->addWidget(m_SwitchSelection, 1, 0, 1, 1, Qt::AlignCenter);
    swLayout->addWidget(m_SwitchChannel, 1, 1, 1, 1, Qt::AlignCenter);
    m_SwitchWidget->setLayout(swLayout);

    QHBoxLayout *hLayout9 = new QHBoxLayout;
    hLayout9->setMargin(0);
    hLayout9->addWidget(m_Con_ConstantRadio);
    hLayout9->addWidget(m_Con_constValueEdit);
    hLayout9->addWidget(new QLabel(tr("dB")));
    QHBoxLayout *hLayout10 = new QHBoxLayout;
    hLayout10->setMargin(0);
    hLayout10->addWidget(m_Con_TableRadio);
    hLayout10->addWidget(m_Con_tableBox, 1);
    QVBoxLayout *vlayout5 = new QVBoxLayout;
    vlayout5->setContentsMargins(5, 15, 5, 9);
    vlayout5->addLayout(hLayout9);
    vlayout5->addLayout(hLayout10);
    vlayout5->addWidget(m_SwitchWidget);
    vlayout5->addStretch();
    m_ConnectorWidget->setLayout(vlayout5);

    m_FieldProbeWidget->setTitle(tr("FieldProbeAttribute"));
    m_FieldProbeWidget->setMaximumWidth(267);
    m_FP_CorrectionTableBox = new QComboBox;
    m_FP_CorrectionTableBox->setToolTip(tr("AttTables"));
    QHBoxLayout *hLayout11 = new QHBoxLayout;
    hLayout11->setMargin(0);
    hLayout11->addWidget(m_FP_CorrectionTableBox, 1);
    QVBoxLayout *vlayout6 = new QVBoxLayout;
    vlayout6->setContentsMargins(5, 15, 5, 9);
    vlayout6->addWidget(new QLabel(tr("CorrectionTable")));
    vlayout6->addLayout(hLayout11);
    vlayout6->addStretch();
    m_FieldProbeWidget->setLayout(vlayout6);

    m_CurrentProbeWidget->setTitle(tr("CurrentProbeAttribute"));
    m_CurrentProbeWidget->setMaximumWidth(267);
    m_CP_TransferCharacteristicTableBox = new QComboBox;
    m_CP_TransferCharacteristicTableBox->setToolTip(tr("TransducerTables"));
    QVBoxLayout *vlayout7 = new QVBoxLayout;
    vlayout7->setContentsMargins(5, 15, 5, 9);
    vlayout7->addWidget(new QLabel(tr("TransferCharacteristicTable"))); //传输属性
    vlayout7->addWidget(m_CP_TransferCharacteristicTableBox);
    vlayout7->addStretch();
    m_CurrentProbeWidget->setLayout(vlayout7);

    m_ReceiverWidget->setTitle(tr("ReceiverAttribute"));
    m_ReceiverWidget->setMaximumWidth(267);
}

/**
 * @brief HardwareWidget::on_pBtn_add_clicked
 * @details 新增硬件模板，支持复制当前模板作为基准。
 */
void HardwareWidget::on_pBtn_add_clicked()
{
    HardwareTemplatePtr newTemplate;
    int currentIndex = ui->tabWidget_ht->currentIndex();
    if (currentIndex < 0 || currentIndex >= presenters_.size()) {
        QString newTemplateName = "hardTemplate";
        int counter = 1;
        QString originalName = newTemplateName;
        while (DataManager::instance()->overVivewNameExists(
            DataManager::instance()->getHardwareTemplateOverviews(), newTemplateName)) {
            newTemplateName = originalName + "(" + QString::number(counter++) + ")";
        }
        newTemplate = DataManager::instance()->addHardwareTemplate(newTemplateName, m_type);
    } else {
        // 从模型中获取选中项的ID
        auto *page = ui->tabWidget_ht->widget(currentIndex);
        auto conns = page->findChildren<ConnectingWindow *>();
        int id = 0;
        if (!conns.isEmpty())
            id = conns.first()->templateId();
        if (id > 0)
            // 调用 DataManager 的复制功能
            newTemplate = DataManager::instance()->duplicateHardwareTemplate(id);
        else
            qWarning() << "get templateId error";
    }
    if (!newTemplate) {
        QMessageBox::critical(this, tr("错误"), tr("新增模板失败"));
        return;
    }

    auto *conn = new ConnectingWindow(m_type, this);
    conn->setData(newTemplate);

    auto *presenter = new HardwareEditorPresenter(newTemplate, conn, this);
    presenter->setSelectedRole(DeviceRole::SignalGenerator);
    presenter->bind();
    presenters_.push_back(presenter);

    // 只放连接图
    auto *page = new QWidget(this);
    auto *h = new QHBoxLayout(page);
    h->setContentsMargins(0, 0, 0, 0);
    h->addWidget(conn);

    ui->tabWidget_ht->addTab(page, newTemplate->name);

    updateComboBoxName();
    ui->tabWidget_ht->setCurrentWidget(conn);
    return;
}

/**
 * @brief HardwareWidget::on_pBtn_del_clicked
 * @details 删除当前选中的硬件模板并更新界面。
 */
void HardwareWidget::on_pBtn_del_clicked()
{
    int currentIndex = ui->tabWidget_ht->currentIndex();
    if (currentIndex < 0)
        return;

    // 找页面内的 ConnectingWindow 获取 id（也可以从 presenter 的 doc 拿）
    auto *page = ui->tabWidget_ht->widget(currentIndex);
    auto conns = page->findChildren<ConnectingWindow *>();
    int id = 0;
    if (!conns.isEmpty())
        id = conns.first()->templateId();

    if (id > 0 && DataManager::instance()->removeHardwareTemplate(id)) {
        ui->tabWidget_ht->removeTab(currentIndex);
        if (currentIndex >= 0 && currentIndex < presenters_.size())
            presenters_.remove(currentIndex);
        updateComboBoxName();
    }
}

/**
 * @brief HardwareWidget::on_tabBarClicked
 * @details 响应标签双击，启用重命名编辑框。
 * @param index 标签索引。
 */
void HardwareWidget::on_tabBarClicked(int index)
{
    ui->tabWidget_ht->setCurrentIndex(index);
    m_tabNameEdit->show();
    m_tabNameEdit->setProperty("tabBarId", index);
    m_tabNameEdit->setText(ui->tabWidget_ht->tabBar()->tabText(index));

    QRect r = ui->tabWidget_ht->tabBar()->tabRect(index);
    QPoint topLeft = ui->tabWidget_ht->tabBar()->mapTo(this, r.topLeft());
    m_tabNameEdit->resize(r.size() - QSize(2, 0));
    m_tabNameEdit->move(topLeft);
    m_tabNameEdit->setFocus();
    m_tabNameEdit->selectAll();
}

/**
 * @brief HardwareWidget::on_setTabName
 * @details 完成标签重命名并刷新相关 UI。
 */
void HardwareWidget::on_setTabName()
{
    QString name = m_tabNameEdit->text();
    int index = m_tabNameEdit->property("tabBarId").toInt();
    if (index >= 0 && index < ui->tabWidget_ht->count()) {
        ui->tabWidget_ht->setTabText(index, name + "*");
    }
    m_tabNameEdit->hide();
    updateComboBoxName();
    ui->tabWidget_ht->setCurrentIndex(index);
}

/**
 * @brief HardwareWidget::on_comboBox_htName_currentIndexChanged
 * @details 通过下拉框选择切换当前模板页。
 * @param index 目标索引。
 */
void HardwareWidget::on_comboBox_htName_currentIndexChanged(int index)
{
    ui->tabWidget_ht->setCurrentIndex(index);
    ui->tabWidget_ht->setFocus();
}

/**
 * @brief HardwareWidget::on_tabWidget_ht_currentChanged
 * @details 切换模板时重绑定属性视图并同步频率范围。
 * @param index 当前标签索引。
 */
void HardwareWidget::on_tabWidget_ht_currentChanged(int index)
{
    // 更新右上 combobox 名称（防误触用 QSignalBlocker）
    QSignalBlocker blk(ui->comboBox_htName);
    ui->comboBox_htName->setCurrentIndex(index);

    // 右侧全局属性面板重绑定
    if (activePresenterIndex_ >= 0 && activePresenterIndex_ < presenters_.size()) {
        presenters_[activePresenterIndex_]->setAttrView(nullptr);
        presenters_[activePresenterIndex_]->setSpecificView(nullptr);
    }
    activePresenterIndex_ = index;
    if (index >= 0 && index < presenters_.size()) {
        presenters_[index]->setAttrView(attrAdapter_);
        presenters_[index]->setSpecificView(specificAdapter_);

        auto *page = ui->tabWidget_ht->widget(index);
        auto conns = page->findChildren<ConnectingWindow *>();
        if (!conns.isEmpty()) {
            auto &doc = conns.first()->getHardwareTemplate();
            if (doc) {
                DataManager::instance()->selectHardwareTemplate(doc->id);
                double maxHz = doc->frequencyMax;
                double minHz = doc->frequencyMin;
                if (maxHz < minHz)
                    maxHz = minHz + 1e6;
                if (maxHz > 40000 * 1e6)
                    maxHz = 40000 * 1e6;
                if (minHz > 40000 * 1e6)
                    minHz = 40000 * 1e6;

                ui->lineEdit_start->setText(QString::number(minHz / 1e6));
                ui->lineEdit_stop->setText(QString::number(maxHz / 1e6));
            }
        }
    } else {
        attrAdapter_->setEnabled(false);
    }
}

/**
 * @brief HardwareWidget::on_pBtn_save_clicked
 * @details 保存当前模板至数据管理器并清除修改标记。
 */
void HardwareWidget::on_pBtn_save_clicked()
{
    int idx = ui->tabWidget_ht->currentIndex();
    if (idx < 0 || idx >= presenters_.size())
        return;

    // 更新文档名（从 tab 文本去掉 *）
    auto *page = ui->tabWidget_ht->widget(idx);
    auto conns = page->findChildren<ConnectingWindow *>();
    HardwareTemplatePtr doc;
    if (!conns.isEmpty())
        doc = conns.first()->getHardwareTemplate();

    if (doc) {
        QString name = ui->tabWidget_ht->tabText(idx);
        name.remove('*');
        doc->name = name;
        // 若有起止频率编辑框，可在此同步：
        double maxHz = ui->lineEdit_stop->text().toDouble() * 1e6;
        double minHz = ui->lineEdit_start->text().toDouble() * 1e6;
        if (maxHz <= minHz)
            maxHz = minHz + 1e6;

        if (minHz > 40000 * 1e6)
            minHz = 40000 * 1e6;
        if (maxHz > 40000 * 1e6)
            maxHz = 40000 * 1e6;

        doc->frequencyMin = minHz;
        doc->frequencyMax = maxHz;
        ui->lineEdit_start->setText(QString::number(minHz / 1e6));
        ui->lineEdit_stop->setText(QString::number(maxHz / 1e6));
    }

    QString err;
    if (!presenters_[idx]->save(&err)) {
        QMessageBox::critical(this, tr("保存失败"), err);
        return;
    }

    // 去掉 *
    ui->tabWidget_ht->setTabText(idx, doc ? doc->name : ui->tabWidget_ht->tabText(idx));
    updateComboBoxName();
    QMessageBox::information(this, tr("成功"), tr("硬件模板已保存。"));
}
